﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Configuration;
using Widgetsphere.Autos.API.FacetedNavigation;

namespace Widgetsphere.Autos.Websitev2.Objects
{
	internal static class ResultsCacheHelper
	{
		//public static ListingResults Query(ListingQuery query)
		//{
		//  var key = query.ToString();
		//  var results = HttpContext.Current.Cache[key] as ListingResults;
		//  if (results == null)
		//  {
		//    results = RepositoryHelper.Query(query);
		//    HttpContext.Current.Cache.Add(
		//      key,
		//      results,
		//      null,
		//      DateTime.Now.AddMinutes(60),
		//      TimeSpan.Zero,
		//      CacheItemPriority.Default, null);
		//  }
		//  return results;
		//}

		private static int GetCacheLimit()
		{
			int retval;
			if (int.TryParse(ConfigurationManager.AppSettings["CacheTime"], out retval))
			{
				if (retval < 1) retval = 1;
				return retval;
			}
			else return 60;
		}

		public static ListingResults Query(ListingQuery query)
		{
			//var key = query.ToString();
			////var results = ReadFromDisk(query); //TODO
			//ListingResults results = null;
			//if (results == null)
			//{
			//  results = RepositoryHelper.Query(query);
			//  WriteToDisk(query, results);
			//}
			//return results;

			return RepositoryHelper.Query(query);
		}

		private static ListingResults ReadFromDisk(ListingQuery query)
		{
			var fileName = GetCacheFileName(query);
			if (File.Exists(fileName))
			{
				//If the file exists and too old then remove it
				var fi = new FileInfo(fileName);
				if (DateTime.Now.Subtract(fi.CreationTime).TotalMinutes > GetCacheLimit())
					fi.Delete();
			}

			//If the file exists read it
			if (File.Exists(fileName))
			{
				var a = System.IO.File.OpenRead(fileName);
				var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
				var results = bf.Deserialize(a) as ListingResults;
				a.Close();
				//results.ComputeTime = -1;
				return results;
			}

			//Otherwise there is nothing to read
			return null;
		}

		private static void WriteToDisk(ListingQuery query, ListingResults results)
		{
			//Remove the file if it exists
			var fileName = GetCacheFileName(query);
			if (File.Exists(fileName))
			File.Delete(fileName);

			//Write a new file
			var a = System.IO.File.OpenWrite(fileName);
			var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
			bf.Serialize(a, results);
			a.Close();
		}

		private static string GetCacheFileName(ListingQuery query)
		{
			var key = GetKey(query);
			var fileName = Path.Combine(HttpContext.Current.Server.MapPath("~"), "cache");

			//Create it if need be
			if (!Directory.Exists(fileName))
				Directory.CreateDirectory(fileName);

			return Path.Combine(fileName, key);
		}

		private static string GetKey(ListingQuery query)
		{
			var plainText = query.ToString();
			var tmpSource = ASCIIEncoding.ASCII.GetBytes(plainText);
			var tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
			return ByteArrayToString(tmpHash);
		}

		private static string ByteArrayToString(byte[] arrInput)
		{
			int i;
			var sOutput = new StringBuilder(arrInput.Length);
			for (i = 0; i < arrInput.Length; i++)
			{
				sOutput.Append(arrInput[i].ToString("X2"));
			}
			return sOutput.ToString();
		}
		
	}
}